/*************************************************************************
    > File Name: socket.h
    > Author: 侯广臣
    > Mail: 2801059691@qq.com 
    > Created Time: 2020年12月30日 星期三 14时46分24秒
 ************************************************************************/
#ifndef _SOCKET_H_
#define _SOCKET_H_

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/sendfile.h>

class CSocket
{
	private:
		int m_sockfd;

	public:
		//初始化套接字
		CSocket(const int sockfd) : m_sockfd(sockfd){	}
		//关闭套接字释放资源
		~CSocket(){ close(m_sockfd); }
		//接受信息
		ssize_t Recv(char *buf, int bufSize, const int flag = 0);
		//发送信息
		ssize_t Send(const char *buf, int bufSize, const int flag = 0);
		//传输文件，inFd必须为真实文件描述符，成功返回字节数，失败返回 -1
		ssize_t SendFile(int inFd, size_t count, off_t *offset = NULL);
};

class CListenSocket
{
	private:
		int					m_sockfd;
		struct sockaddr_in	m_clientAddr;
		socklen_t 			m_clientAddrLen;
	
	public:
		//默认构造函数，使用该类其它函数时应调用Init()函数
		CListenSocket() : m_sockfd(-1), m_clientAddrLen(sizeof(struct sockaddr_in)) { }
		//直接构造制成监听套接字
		CListenSocket(const char *ip, int port, int backlog)
		{
			Init(ip, port, backlog);
		}

		~CListenSocket()
		{
			if(m_sockfd != -1)
			{
				close(m_sockfd);
			}
		}

		//返回已连接套接字，失败返回 -1
		int Accept(void)
		{
			return accept(m_sockfd, (struct sockaddr*)&m_clientAddr, &m_clientAddrLen);
		}

		//如果ip == NULL默认监听所有本地地址，如果已经构造过，即m_sockfd != -1，不做动作。
		//失败返回 -1，成功返回m_sockfd
		int Init(const char *ip = NULL, int port = 8888, int backlog = 5);
		
		//把连接客户端的IP地址和端口信息填充到buf所指的地址中，返回buf指针，错误返回NULL
		char* GetClientInfo(char *buf);
};



#endif
